package de.mhu.mandalaui.bind;

import java.io.PrintWriter;

import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.node.ArrayNode;
import org.codehaus.jackson.node.ObjectNode;

import de.mhu.mandalaui.Response;
import de.mhu.mandalaui.actions.Action;
import de.mhu.mandalaui.attributes.Attribute;
import de.mhu.mandalaui.impl.WindowExtended;
import de.mhu.mandalaui.properties.Property;
import de.mhu.mandalaui.remote.RemoteCallable;
import de.mhu.mandalaui.remote.RemoteRegistry;

public class RemoteAction extends Action implements RemoteCallable {

	private Call errorCall;
	private Call successCall;
	private RemoteActionListener listener;
	private RemoteRegistry registry;
	private Attribute dataFillProperty;

	public void startRender(Response response) {
		super.startRender(response);
		if (this.successCall != null) this.successCall.startRender(response);
		if (this.errorCall != null) this.errorCall.startRender(response);
	}

	@Override
	public void doRemoteCall(JsonNode in, JsonGenerator out, String requestId)
			throws Exception {
		ObjectMapper mapper = new ObjectMapper();
		ObjectNode node = mapper.createObjectNode();
		node.put("requestId", requestId);
		try {
			
			ArrayNode result = node.putArray("result");

			listener.doExecute(in, result);
			
			node.put("success", 1);
		} catch (Throwable t) {
			node.put("success", 0);
			node.put("error_msg", t.getMessage());
			t.printStackTrace();
		}
		
		out.setCodec(mapper);
		out.writeTree(node);
	}

	@Override
	public void renderFunctionImplementation(PrintWriter out) {
		if (this.successCall != null) this.successCall.setOwner(getOwner());
		if (this.errorCall != null) this.errorCall.setOwner(getOwner());

		if (registry == null)
			registry = getWindow().registerRemoteCall(this);
		
		out.println("function(data) {");
		if (dataFillProperty != null) {
			out.print("data = ");
			dataFillProperty.renderGet(out);
			out.println(";");
		}
		out.print("  var url = '");
		out.print(registry.getUrl());
		out.print("&_mandala_request_id='+ Math.random() +'");
		out.println("&data=' + encodeURIComponent(JSON.stringify(data));");
		if (getWindow() instanceof WindowExtended) ((WindowExtended)getWindow()).beforeRemoteCall(out,"url");
		out.println("  $.getJSON(url, function (data2) {");
		if (getWindow() instanceof WindowExtended) ((WindowExtended)getWindow()).afterRemoteCall(out,"data2");
		out.println("        if (data2.success == 1) {");
		if (getSuccessCall() != null) getSuccessCall().renderFunctionCall(out, true);
		out.println("} else {");
		if (errorCall != null) errorCall.renderFunctionCall(out, true);
		out.println("} }); }");
	}

	public Call getErrorCall() {
		return errorCall;
	}

	public void setErrorCall(Call errorCall) {
		this.errorCall = errorCall;
	}


	public Call getSuccessCall() {
		return successCall;
	}

	public void setSuccessCall(Call successCall) {
		this.successCall = successCall;
	}

	public RemoteActionListener getListener() {
		return listener;
	}

	public void setListener(RemoteActionListener listener) {
		this.listener = listener;
	}

	public Attribute getDataFillProperty() {
		return dataFillProperty;
	}

	public void setDataFillProperty(Attribute dataFillProperty) {
		this.dataFillProperty = dataFillProperty;
	}

}
